home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / AWE32PRG.ZIP / AWE32P10.TXT next >
Text File  |  1995-10-04  |  51KB  |  1,369 lines

  1.         
  2.        =========================================================
  3.       || The Un-official Sound Blaster AWE32 Programming Guide ||
  4.       ||                                                       ||
  5.       ||             by Vince Vu a.k.a. Judge Dredd            ||
  6.       ||                                                       ||
  7.       ||             V.1.0 September 28, 1995                  ||
  8.        =========================================================
  9.  
  10.  
  11. Table of Contents
  12. -----------------
  13.  
  14. 1.    Last minute notes
  15.  
  16. I.    Introduction
  17.  
  18. II.   Understanding the registers
  19.  
  20. III.  Detection
  21.  
  22. IV.   Initialization
  23.  
  24. V.    Sample uploading/downloading
  25.  
  26. VI.   Playing a sample
  27.  
  28. VII.  The registers        
  29.  
  30. VIII. Effects Engine data.
  31.  
  32. IX.   Other documents you should refer to.
  33.  
  34.  
  35.  
  36. 1.    Last minute notes
  37. -----------------------
  38.  
  39. Yes, I know most of this is poorly written.  (Thoughts not carefully
  40. organized).  But if you have any questions, of misunderstandings, or
  41. difficulties, *mail me*.
  42.  
  43. I like getting mail.  It helps feed my ego ;)
  44.  
  45. BTW Don't believe any of the b.s. Creative Labs says about the effects
  46. engine on the EMU8000 not being programmable, because it is.  Please
  47. pester them to release info on the effects engine.
  48.  
  49. Greets:
  50.  
  51.         Morbius         My homie.
  52.         Thor            Cool Hungarian dude that wrote AWEPlay
  53.         BLR             BlazeRuner, long time no see.
  54.         Darron Myrick   Here's the whole enchilada.
  55.         Mathias Hjelt   Now, you can tweak your AWE32 to perfection.
  56.                         Maybe...
  57.  
  58.         And...
  59.  
  60.         All the other guys, gals, neuters, etc... not mentioned.
  61.  
  62.  
  63. I.    Introduction
  64. ------------------
  65.  
  66. Mail all questions, comments, etc... to jdredd@netcom.com
  67.  
  68. Well, a month overdue, but its finally here.  This guide will attempt to 
  69. describe in detail how to program the EMU8000 chip on the Sound Blaster AWE32,
  70. directly.  This past summer, I spent nearly a month, figuring out how to
  71. program the EMU8000 on a low-level.  And I succeeded.  This is a compilation 
  72. of all that I figured out, and please, if you use this information in any
  73. production, program, etc..., acknowledge me.
  74.  
  75. Why am I writing down and distributing my hard-earned knowledge?  Well, after
  76. reading an AWE32 in demos thread on comp.sys.ibm.pc.demos, I realized that the 
  77. best way to improve the AWE32's status would be to release a programming
  78. guide.
  79.  
  80. This document will not cover Sound Blaster basics, only the EMU8000 sub-system
  81. on the SBAWE32 card.  If you need info on programming the OPL3, the DAC/ADC,
  82. or the mixer then you need to refer to a SB16 programming guide.
  83.  
  84. Umm... please refer to the register list in section VII, when reading this
  85. document, in case you have trouble with recognizing what register 0x5400 or
  86. something else is.
  87.  
  88. The EMU8000 Specs:
  89.  
  90. 32 Oscillators of 16-Bit, 44100Hz sound.
  91. 32 Megabytes of address space.  The first 4 or reserved for ROM, and the last
  92.    28 are for RAM.  Internally the EMU8000 only has 24-Bit address space.  So
  93.    only 16-bit samples can be used.
  94. 3  Point sample interpolation.
  95. 1  Onboard Digital Effects Processor.
  96. 2  Low Frequency Oscillators' per oscillator.
  97. 2  DAHDSR Envelope Generators' per oscillator.
  98. 1  Resonant Filter per oscillator.
  99. 32 Independant reverb send levels for each oscillator.
  100. 32 Independant chorus send levels for each oscillator.
  101. 1  SP/DIF Digital Output.
  102.  
  103. Glossary:
  104.  
  105. EG1     Envelope Generator 1 (Filter/Pitch)
  106. EG2     Envelope Generator 2 (Volume)
  107. LFO1    Low Frequency Oscillator 1 (Pitch/Volume/Filter)
  108. LFO2    Low Frequency Oscillator 2 (Pitch)
  109. FilterQ Filter Resonance
  110.  
  111. Explaination of EG's:
  112.  
  113. Delay:  The time before the attack, during which the envelope's
  114.         level stays at 0.
  115. Attack: The time during which the envelope's level fades from
  116.         0 to peak.
  117. Hold:   The time before the decay, during which the envelope's
  118.         level stays at peak.
  119. Decay:  The time during which the envelope's level fades from peak
  120.         to the sustain level.
  121. Sustain:The level at which the envelope stays before release.
  122. Release:The time during which the envelope's level fades from sustain
  123.         to 0.
  124.  
  125.         _
  126.       /   \ __
  127. ____/          \
  128.  
  129. ^    ^  ^^  ^  ^
  130. |    |  ||  |  |
  131. |    |  ||  |   - Release Time
  132. |    |  ||   ---- Sustain Level
  133. |    |  | ------- Decay Time
  134. |    |    ------- Hold Time
  135. |     ----------- Attack Time
  136.  ---------------- Delay Time
  137.  
  138.  
  139. II.   Understanding the registers
  140. ---------------------------------
  141.  
  142. Here are the ports that are mapped to the EMU8000 (they are all word ports):
  143.  
  144.         0x620   Data Read/Write
  145.         0x622   Data Read/Write
  146.         0xA20   Data Read/Write
  147.         0xA22   Data Read/Write
  148.         0xE20   Data Read/Write
  149.         0xE22   Index
  150.  
  151. Simply replace the middle digit of the port with the proper base.  e.g. 0xE30
  152. if the SBAWE32's base port is 0x230.  The rest of this document will refer to 
  153. the ports as 0x620, 0xE20, etc...  But remember to replace the middle digit.
  154.        
  155. In order to write or read from a register, one would first have to select the 
  156. proper index (if not already selected) by writing the index to the index port,
  157. 0xE22.
  158.  
  159. Example:
  160.  
  161.         outpw(0xE22, 0);
  162.  
  163. That's it.  Now that you have selected the proper index you can now write/read
  164. the data from the anyone of the registers that uses that index, by
  165. reading/writing the correct port.
  166.  
  167. Example:
  168.  
  169.         outpw(0xE20, 57344);    //Port 0xE20, Index 0, is the pitch register
  170.                                 //for oscillator 0.
  171.  
  172. Some registers, however, maybe 32-bits (double word), writing to them is
  173. almost the same as writing to a 16-bit register as above.
  174.  
  175. Example:
  176.  
  177.         outpw(0xA20, 0x0000);   //Port 0xA20, Index 0 is the 
  178.                                 //FilterQ/DramControl/PlayPosition register
  179.         outpw(0xA22, 0x0002);   //for oscillator 0.  What we just did is write
  180.                                 //the low word to
  181.                                 //0xA20, and then write the high word to
  182.                                 //0xA22.
  183.  
  184. Reading from a register is exactly the same as writing, except you read (in)
  185. from that port instead of write.
  186.  
  187.  
  188. IMPORTANT!!!  MUST READ!!!
  189.  
  190. For the rest of this document I will refer to registers the following way:
  191.  
  192.         0x141d
  193.           ^^^^
  194.           || |
  195.           ||  - The oscillator number in hex.  Here it is 0x1d or 29 in
  196.           ||    decimal.
  197.           ||
  198.           | --- The port. 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20.  Here it
  199.           |     is 4, 0xA20.
  200.           |
  201.            ---- The base index.  Multiply by 32 and add the oscillator number to
  202.                 get the real index, to write to 0xE22.  Here it is 1, so the base
  203.                 index is 32.
  204.  
  205. III.  Detection
  206. ---------------
  207.  
  208. There are several methods for detecting the presence of the EMU8000.  But I
  209. will only show one way.  Here's a simple detection routine in Ansi C:
  210.  
  211. int awe32Detect(unsigned baseport) {
  212.  
  213.         int scratch;
  214.  
  215.         outpw(0xc02+baseport, 224);     //Select index 224 by writing to 0xe22
  216.         inpw(0xc00+baseport);           //Read from port 0xe20
  217.         scratch = inpw(0xc00+baseport); //Read from port 0xe20 again
  218.  
  219.         if((scratch&0xf) != 0xc)
  220.                 return 1;               //Not detected
  221.  
  222.         outpw(0xc02+baseport, 51);      //Select index 51 (base index 32,
  223.                                         //oscillator 29)
  224.         scratch = inpw(0x800+baseport); //Read from port 0xa20
  225.  
  226.         if((scratch&0x7e) != 0x58)
  227.                 return 1;               //Not detected
  228.  
  229.         outpw(0xc02+baseport, 52);      //Select index 52 (base index 32, 
  230.                                         //oscillator 30)
  231.         scratch = inpw(0x800+baseport); //Read from port 0xa20
  232.  
  233.         if((scratch&0x03) != 0x03)
  234.                 return  1;              //Not detected
  235.  
  236.         return 0;                       //Woo-hoo! Detected!
  237.  
  238. }
  239.  
  240.  
  241.  
  242. IV.   Initialization
  243. --------------------
  244.  
  245. The most complex part of programming the EMU8000 is probably initialization.
  246. There are several things you can initialize, but you do not have to.  You 
  247. should initialize the effects engine.  You should initialize OPL3/FM pass-
  248. through, which also enables DRAM refresh.  And you should detect the ammount
  249. of DRAM.  oh, and you should also stop all oscillators from playing, just in
  250. case they are.
  251.  
  252. You should do those things in this order:
  253.  
  254. Stop the oscillators from playing, just in case.
  255. Initialize the Effects Engine.
  256. Initialize the FM Passthrough (You don't need to if you use only ROM sounds)
  257. Detect the DRAM
  258.  
  259. Initializing the effects engine:
  260.  
  261. Registers 0x2400 through 0x361f are entirely devoted to effects engine data.
  262. In order to initialize the effects engine, here's C code to intialize the
  263. engine to Reverb&Chorus:
  264.  
  265. -------------------------------------------------------------------------------
  266.  
  267. unsigned Reset_FX[128] = {...}          //The real data is in section VIII. of
  268.                                         //this document.
  269. unsigned Reverb&Chorus_FX[128] = {...}  //The real data is in section VIII. of
  270.                                         //this document.
  271. unsigned clock_wait;
  272.  
  273. outpw(0xE22, 32+20);                    //Select base index 32+oscillator 20
  274. outpw(0xA20, 0);
  275.  
  276. outpw(0xE22, 32+21);                    //Select base index 32+oscillator 21
  277. outpw(0xA20, 0);
  278.  
  279. outpw(0xE22, 32+22);                    //Select base index 32+oscillator 22
  280. outpw(0xA20, 0);
  281.  
  282. outpw(0xE22, 32+23);                    //Select base index 32+oscillator 23
  283. outpw(0xA20, 0);
  284.  
  285. outpw(0xE22, 32+21);                    //Select base index 32+oscillator 21
  286. outpw(0xA20, 0);
  287.  
  288.  
  289. for(i=0; i<32; i++) {
  290.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  291.                                         //number
  292.         outpw(0xA22, Reset_FX[i]);
  293. }
  294. for(i=0; i<32; i++) {
  295.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  296.                                         //number
  297.         outpw(0xA20, Reset_FX[32+i]);
  298. }
  299. for(i=0; i<32; i++) {
  300.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  301.                                         //number
  302.         outpw(0xA22, Reset_FX[64+i]);
  303. }
  304. for(i=0; i<32; i++) {
  305.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  306.                                         //number
  307.         outpw(0xA20, Reset_FX[96+i]);
  308. }
  309.  
  310. outpw(0xE22, 32+27);                    //Select base index 32+oscillator 27
  311. clock = inpw(0xA22);                    //This is the 44100Hz clock counter.
  312. clock += 0x400;                         //Add 1024 to the counter.
  313.  
  314. if((clock-0x400)<clock)                 //Do this just in case clock
  315.                                         //overflowed
  316.         while(inpw(0xA22)>clock);       //i.e. clock went past 65535
  317. while(inpw(0xA22)<clock);               //Wait 1024*1/44100 seconds
  318.  
  319. for(i=0; i<20; i++) {
  320.         outpw(0xE22, 32+i);             //Select base index 32+oscillator
  321.                                         //number
  322.         outpw(0xA20, 0);                //These are 32-bit registers
  323.         outpw(0xA22, 0);
  324. }
  325.  
  326. for(i=0; i<32; i++) {
  327.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  328.                                         //number
  329.         outpw(0xA22, Reset_FX[i]);
  330. }
  331.  
  332.  
  333. for(i=0; i<32; i++) {
  334.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  335.                                         //number
  336.         if(i&1)
  337.                 outpw(0xA20, 0x8000|Reset_FX[i]);
  338.         else
  339.                 outpw(0xA20, Reset_FX[i]
  340. }
  341. for(i=0; i<32; i++) {
  342.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  343.                                         //number
  344.         if(i&1)
  345.                 outpw(0xA20, 0x8000|Reset_FX[32+i]);
  346.         else
  347.                 outpw(0xA20, Reset_FX[32+i]
  348. }
  349. for(i=0; i<32; i++) {
  350.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  351.                                         //number
  352.         if(i&1)
  353.                 outpw(0xA20, 0x8000|Reset_FX[64+i]);
  354.         else
  355.                 outpw(0xA20, Reset_FX[64+i]
  356. }
  357. for(i=0; i<32; i++) {
  358.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  359.                                         //number
  360.         if(i&1)
  361.                 outpw(0xA20, 0x8000|Reset_FX[96+i]);
  362.         else
  363.                 outpw(0xA20, Reset_FX[96+i]
  364. }
  365.  
  366.  
  367. /* Upload the Reverb&Chorus Algorithm */
  368. for(i=0; i<32; i++) {
  369.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  370.                                         //number
  371.         if(i&1)
  372.                 outpw(0xA20, 0x8000|Reverb&Chorus_FX[i]);
  373.         else
  374.                 outpw(0xA20, Reverb&Chorus_FX[i]
  375. }
  376. for(i=0; i<32; i++) {
  377.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  378.                                         //number
  379.         if(i&1)
  380.                 outpw(0xA20, 0x8000|Reverb&Chorus_FX[32+i]);
  381.         else
  382.                 outpw(0xA20, Reverb&Chorus_FX[32+i]
  383. }
  384. for(i=0; i<32; i++) {
  385.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  386.                                         //number
  387.         if(i&1)
  388.                 outpw(0xA20, 0x8000|Reverb&Chorus_FX[64+i]);
  389.         else
  390.                 outpw(0xA20, Reverb&Chorus_FX[64+i]
  391. }
  392. for(i=0; i<32; i++) {
  393.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  394.                                         //number
  395.         if(i&1)
  396.                 outpw(0xA20, 0x8000|Reverb&Chorus_FX[96+i]);
  397.         else
  398.                 outpw(0xA20, Reverb&Chorus_FX[96+i]
  399. }
  400.  
  401. outpw(0xE22, 32+9);                     //Select base index 32+oscillator 9
  402. outpw(0xA20, 0);                        //This register holds an unknown chorus
  403.                                         //parameter
  404. outpw(0xA22, 0);                        //for the Reverb&Chorus Algorithm
  405.  
  406. outpw(0xE22, 32+10);                    //Select base index 32+oscillator 10
  407. outpw(0xA20, 0x83);                     //This register holds the chorus
  408. outpw(0xA22, 0x00);                     //parameter for chorus modulation
  409.                                         //frequency
  410.  
  411. outpw(0xE22, 32+13);                    //Select base index 32+oscillator 13
  412. outpw(0xA20, 0);                        //This register holds an unknown chorus
  413. outpw(0xA22, 80);                       //parameter for the Reverb&Chorus 
  414.                                         //Algorithm
  415.  
  416. outpw(0xE22, 32+14);                    //Select base index 32+oscillator 13
  417. outpw(0xA20, 0);                        //This register holds an unknown chorus
  418. outpw(0xA22, 0);                        //parameter for the Reverb&Chorus
  419.                                         //Algorithm
  420.  
  421. for(i=0; i<32; i++) {
  422.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  423.                                         //number
  424.         outpw(0xA20, Reverb&Chorus_FX[i]
  425. }
  426. for(i=0; i<32; i++) {
  427.         outpw(0xE22, 96+i);             //Select base index 96+oscillator
  428.                                         //number
  429.         outpw(0xA20, Reverb&Chorus_FX[32+i]
  430. }
  431. for(i=0; i<32; i++) {
  432.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  433.                                         //number
  434.         outpw(0xA20, Reverb&Chorus_FX[64+i]
  435. }
  436. for(i=0; i<32; i++) {
  437.         outpw(0xE22, 64+(i/32));        //Select base index 64+oscillator
  438.                                         //number
  439.         outpw(0xA20, Reverb&Chorus_FX[96+i]
  440. }
  441.         
  442. return;
  443.  
  444. --------------------------------------------------------------------------------
  445.  
  446. Wowie, that's it!  Obviously, this code is not optimized.  Some of the 
  447. outpw's to select the index, are redundant.  But speed is not crucial, because
  448. this is an initialization routine.
  449.  
  450. Initializing FM Passthrough:
  451.  
  452. This routine is uses a timing loop to synchronize the oscillator with the
  453. refreshing of the DRAM.  Which also enables OPL3 passthrough.
  454.  
  455. Here's a list of what to do:
  456.  
  457.     Write 0x0080 to 0x541E (16-bit), the EG2 volume ramp register for
  458.     oscillator 30.  This disables EG2, from affecting volume.
  459.  
  460.     Write 0xFFFFFFE0 to 0x601E (32-bit), the loopstart/pan register.
  461.     This sets the pan to 0xFF (full left), and the loopstart to
  462.     0xFFFFE0 for oscillator 30.  Of course you can set the pan to whatever
  463.     you like.
  464.  
  465.     Write 0x00FFFFE8 to 0x701E (32-bit), the loopend/chorus send register.
  466.     This sets the chorus send to 0x00 (no send), and the loopend to
  467.     0xFFFFE8 for oscillator 30.  Of course, you can set the chorus send to
  468.     whatever you like.
  469.  
  470.     Write 0x00000000 to 0x101E (32-bit), the ??/reverb send/?? register.
  471.     This sets the reverb send to 0x00 (no send), the oscillator frequency
  472.     to 0x0000 Hz, and other things I don't know.  Yes, you can change the
  473.     reverb send to your liking.
  474.     
  475.     Write 0x00000000 to 0x001E (32-Bit,  I have no idea what this does, but
  476.     it is for oscillator 30 (duh.).
  477.  
  478.     Write 0x00FFFFE3 to 0x041E (32-Bit, the FilterQ/DramControl/PlayPosition
  479.     This sets the FilterQ to 0, DramControl to normal, and PlayPosition to
  480.     0xFFFFE3.  Yes you can set the FilterQ to your liking.
  481.  
  482.     Write 0x0080 to 0x541F (16-bit), the EG2 volume ramp register for
  483.     oscillator 31.  This disables EG2, from affecting volume.
  484.  
  485.     Write 0x00FFFFF0 to 0x601F (32-bit), the loopstart/pan register.
  486.     This sets the pan to 0xFF (full right), and the loopstart to
  487.     0xFFFFF0 for oscillator 31.  Of course you can set the pan to whatever
  488.     you like.
  489.  
  490.     Write 0x00FFFFF8 to 0x701F (32-bit), the loopend/chorus send register.
  491.     This sets the chorus send to 0x00 (no send), and the loopend to
  492.     0xFFFFF8 for oscillator 31.  Of course, you can set the chorus send to
  493.     whatever you like.
  494.  
  495.     Write 0x000000FF to 0x101F (32-bit), the ??/reverb send/?? register.
  496.     This sets the reverb send to 0x00 (no send), the oscillator frequency
  497.     to 0x0000 Hz, and other things I don't know.  Yes, you can change the
  498.     reverb send to your liking.
  499.     
  500.     Write 0x00000000 to 0x001F (32-Bit,  I have no idea what this does, but
  501.     it is for oscillator 31 (duh.).
  502.  
  503.     Write 0x00FFFFF3 to 0x041F (32-Bit, the FilterQ/DramControl/PlayPosition
  504.     This sets the FilterQ to 0, DramControl to normal, and PlayPosition to
  505.     0xFFFFF3.  Yes you can set the FilterQ to your liking.
  506.  
  507.     Okay, this is the crucial timing loop, ill have to show it in C:
  508.  
  509. --------------------------------------------------------------------------------
  510.     outpw(0xE22, 32+30);                //Select index
  511.     outpw(0x620, 0);                    //Register 0x101E
  512.                                         //Recall that 0x101E is 32-Bit
  513.                                         //But do not write to the high word
  514.  
  515.     while(!(inpw(0xE22)&0x1000));       //Wait for that bit to set
  516.     while(inpw(0xE22)&0x1000);          //Wait for that bit to clear
  517.  
  518.     outpw(0x622, 0x4828);               //Okay, now write the high word
  519.                                         //This sets the frequency for
  520.                                         //oscillator 30 to ???
  521.  
  522.     outpw(0xE22, 32+28);                //Select index
  523.     outpw(0xA20, 0);                    //Register 0x141C
  524.  
  525.     outpw(0xE22, 96+30);                //Select index 96, oscillator 30
  526.     outpw(0x620, 0xFFFF);               //Register 0x301E (32-Bit)
  527.     outpw(0x622, 0xFFFF);               //This sets the overall volume (after
  528.                                         //EG2
  529.                                         //and LFO1) to 0xFFFF, and the overall
  530.                                         //filter to 0xFFFF(after LFO1 and EG1)
  531.     outpw(0xE22, 96+31);                //Same as above except for oscillator
  532.     outpw(0x620, 0xFFFF);               //31
  533.     outpw(0x622, 0xFFFF);
  534.  
  535. --------------------------------------------------------------------------------
  536.  
  537. Detecting DRAM:
  538.  
  539. Basically, to detect the ammount of DRAM, you write a sample to an offset in
  540. the memory, and then read from that offset to check if it was actually
  541. written, and make sure the actual write offset did not wrap around.  
  542.  
  543. Here's a detection routine in C:
  544.  
  545. -------------------------------------------------------------------------------
  546.  
  547.         unsigned long dramsize;
  548.         unsigned i;
  549.  
  550. /* Setup 15 Oscillators for DRAM writing, and 15 for read */
  551.  
  552.         for(i=0; i<30; i++) {
  553.         
  554.         outpw(0xE22, 160+i);            //Select Index (i won't comment these
  555.                                         //anymore)
  556.         outpw(0xA20, 0x80);             //Disable EG2, register 0x5400|i
  557.  
  558.         outpw(0xE22, 96+i);
  559.         outpw(0x620, 0x0000);           //Register 0x3000+i
  560.         outpw(0x622, 0x0000);           //Set RawFilter/Raw Volume to 0
  561.  
  562.         outpw(0xE22, 64+i);
  563.         outpw(0x620, 0x0000);           //Register 0x2000+i
  564.         outpw(0x622, 0x0000);           //I don't know what this does
  565.  
  566.         outpw(0xE22, 192+i);
  567.         outpw(0x620, 0x0000);           //Register 0x6000+i
  568.         outpw(0x622, 0x0000);           //Set pan, and loopstart to 0
  569.         
  570.         outpw(0xE22, 224+i);
  571.         outpw(0x620, 0x0000);           //Register 0x7000+i
  572.         outpw(0x622, 0x0000);           //Set chorus send, and loopend to 0
  573.  
  574.         outpw(0xE22, 32+i);
  575.         outpw(0x620, 0x0000);           //Register 0x1000+i
  576.         outpw(0x622, 0x4000);           //Set frequency to ???
  577.  
  578.         outpw(0xE22, 0+i);
  579.         outpw(0x620, 0x0000);           //Register 0x0000+i
  580.         outpw(0x622, 0x4000);           //I don't know what this does
  581.  
  582.         outpw(0xE22, 0+i);
  583.         outpw(0xA20, 0x0000);           //Register 0x0400+i
  584.         if(i&1)
  585.                 outpw(0xA22, 0x0600);   //Write mode
  586.         else
  587.                 outpw(0xA22, 0x0400);   //Read mode
  588.         
  589.         }
  590.  
  591.         outpw(0xE22, 32+22);            //Register 0x1416
  592.         outpw(0xA20, 0x0000);           //Set write offset to 0x200000
  593.         outpw(0xA22, 0x0020);           //(the beginning of DRAM)
  594.  
  595.         outpw(0xE22, 32+26);            //Index for register 0x141A
  596.                                         //this register is the read/write
  597.                                         //data register.
  598.         
  599.         outpw(0xA20, 0xFFFF);           //Write 0xFFFF to offset 0x200000
  600.                                         //0x1416 (write offset register)
  601.                                         //is automatically incremented by
  602.                                         //one every write.
  603.         outpw(0xA20, 0xAAAA);           //Write 0xAAAA to offset 0x200001
  604.         outpw(0xA20, 0x5555);           //Write 0x5555 to offset 0x200002
  605.  
  606.         outpw(0xE22, 32+20);            //Register 0x1414
  607.         outpw(0xA20, 0x0000);           //Set read offset to 0x200000
  608.         outpw(0xA22, 0x0020);
  609.  
  610.         outpw(0xE22, 32+26);            //Set index for register 0x141A
  611.  
  612.         inpw(0xA20);                    //Ignore the first read.
  613.  
  614.         if(inpw(0xA20) != 0xFFFF)
  615.                 return 0;               //No DRAM Detected
  616.         if(inpw(0xA20) != 0xAAAA)
  617.                 return 0;               //No DRAM Detected
  618.         if(inpw(0xA20) != 0x5555)
  619.                 return 0;               //No DRAM Detected
  620.  
  621.         dramsize = 0;
  622.  
  623. while(dramsize<0xdf8000) {
  624.  
  625.         dramsize += 0x20000;            //Everything checks out
  626.                                         //so add 0x20000 to dramsize
  627.         
  628.         outpw(0xE22, 32+22);            //Set the write offset
  629.         outpw(0xA20, (dramsize+0x200000)&0xFFFF);
  630.         outpw(0xA22, (dramsize+0x200000)>>16);
  631.  
  632.         outpw(0xE22, 32+26);            //Select register 0x141A
  633.         
  634.         outpw(0xA20, 0x1234);           //Write 0x1234 to memory
  635.         outpw(0xA20, 0x1234);           //Write it to the next offset.
  636.         outpw(0xA20, 0x1234);           //Write it to the next offset.
  637.  
  638.         outpw(0xE22, 32+20);            //Register 0x1414
  639.         outpw(0xA20, 0x0000);           //Set the read offset to begginning
  640.         outpw(0xA20, 0x0020);           //of DRAM
  641.  
  642.         /* Check for wrap around */
  643.  
  644.         outpw(0xE22, 32+26);            //Set index for register 0x141A
  645.         inpw(0xA20);                    //Ignore the first read.
  646.         if(inpw(0xA20) != 0xFFFF)
  647.                 return dramsize;        //Write wrapped around
  648.         
  649.         /* Check to make sure it was written */
  650.         
  651.         outpw(0xE22, 32+20);            //Register 0x1414 (read offset)
  652.         outpw(0xA20, (dramsize+0x200000)&0xFFFF);
  653.         outpw(0xA22, (dramsize+0x200000)>>16);
  654.  
  655.         outpw(0xE22, 32+26);            //Set index for register 0x141A
  656.         inpw(0xA20);                    //Ignore the first read.
  657.         if(inpw(0xA20) != 0x1234)
  658.                 return dramsize;        //Did not write!
  659.         if(inpw(0xA20) != 0x1234)
  660.                 return dramsize;        //Did not write!
  661.         if(inpw(0xA20) != 0x1234)
  662.                 return dramsize;        //Did not write!
  663.  
  664. }
  665.  
  666.         /* Reset the oscillators */
  667.         for(i=0; i<30; i++) {
  668.                 outpw(0xE22, 0+i);
  669.                 outpw(0xA20, 0x0000);
  670.                 outpw(0xA22, 0x0000);
  671.                 
  672.                 outpw(0xE22, 160+i);
  673.                 outpw(0xA20, 0x807F);
  674.         }
  675.  
  676.         return dramsize;
  677.         
  678. --------------------------------------------------------------------------------
  679.  
  680. The dramsize is returned in words, so you need to multiply by 2 to get the
  681. number of bytes.
  682.  
  683.  
  684. V.    Sample Uploading/Downloading
  685. ----------------------------------
  686.  
  687. When I say uploading, I mean transferring samples from your computer to
  688. the EMU8000's memory.  And downloading is transferring samples from the
  689. EMU8000's memory (ROM included) to your computer.
  690.  
  691. All transfers are done through I/O ports, and not DMA.
  692.  
  693. This is the simplest part of programming the EMU8000.  Here's C code
  694. to setup the oscillators for transfering:
  695.  
  696. -------------------------------------------------------------------------------
  697. /* i is the oscillator number (0-31) */
  698.  
  699.         outpw(0xE22, 160+i);            //Select Index (i won't comment these
  700.                                         //anymore)
  701.         outpw(0xA20, 0x80);             //Disable EG2, register 0x5400|i
  702.  
  703.         outpw(0xE22, 96+i);
  704.         outpw(0x620, 0x0000);           //Register 0x3000+i
  705.         outpw(0x622, 0x0000);           //Set RawFilter/Raw Volume to 0
  706.  
  707.         outpw(0xE22, 64+i);
  708.         outpw(0x620, 0x0000);           //Register 0x2000+i
  709.         outpw(0x622, 0x0000);           //I don't know what this does
  710.  
  711.         outpw(0xE22, 192+i);
  712.         outpw(0x620, 0x0000);           //Register 0x6000+i
  713.         outpw(0x622, 0x0000);           //Set pan, and loopstart to 0
  714.         
  715.         outpw(0xE22, 224+i);
  716.         outpw(0x620, 0x0000);           //Register 0x7000+i
  717.         outpw(0x622, 0x0000);           //Set chorus send, and loopend to 0
  718.  
  719.         outpw(0xE22, 32+i);
  720.         outpw(0x620, 0x0000);           //Register 0x1000+i
  721.         outpw(0x622, 0x4000);           //Set frequency to ???
  722.  
  723.         outpw(0xE22, 0+i);
  724.         outpw(0x620, 0x0000);           //Register 0x0000+i
  725.         outpw(0x622, 0x4000);           //I don't know what this does
  726.  
  727.         outpw(0xE22, 0+i);
  728.         outpw(0xA20, 0x0000);           //Register 0x0400+i
  729.         outpw(0xA22, 0x0600);           //Write mode
  730.                                         //replace 0x0600 with 0x0400
  731.  
  732. -------------------------------------------------------------------------------
  733.  
  734. You can setup as many oscillators as you want for transferring.  You can setup
  735. as little as 1 and as many as 32.  But if you setup 32, remember to
  736. reinitialize fm passthrough.  The more oscillators you use the faster the
  737. transfers.  You do not have to setup a block of oscillators for transfers.
  738. You can setup say, for example oscillators: 0, 3, 7, and 12.  That is
  739. perfectly fine, and you can transfer samples, while still playing.  Just as 
  740. long as the oscillator you setup for transfer is not in use (playing, or
  741. transferring).
  742.  
  743. Here's pseudo-c code to upload (assuming the oscillators are setup already):
  744.  
  745.         outpw(0xE22, 32+22);
  746.         outpw(0xA20, write_offset&0xFFFF);
  747.         outpw(0xA22, write_offset>>16);
  748.  
  749.         outpw(0xE22, 32+26);
  750.         for(i=0; i<no_samples; i++)
  751.                 outpw(0xA20, sample[i]);        //Samples should be 16-Bit
  752.                                                 //Intel, Signed, PCM
  753.  
  754. That's it.  After you are done with the transfers, reset the oscillators
  755. that you used.  Here's how to reset the oscillator:
  756.  
  757.         outpw(0xE22, 0+i);
  758.         outpw(0xA20, 0x0000);
  759.         outpw(0xA22, 0x0000);
  760.                 
  761.         outpw(0xE22, 160+i);
  762.         outpw(0xA20, 0x807F);
  763.  
  764. i is the oscillator number.
  765.  
  766. Uploading is exactly the same as downloading:
  767.  
  768.         outpw(0xE22, 32+22);
  769.         outpw(0xA20, write_offset&0xFFFF);
  770.         outpw(0xA22, write_offset>>16);
  771.  
  772.         outpw(0xE22, 32+26);
  773.         inpw(0xA20);                    //Discard the first read
  774.                                         //I don't know why, but do it.
  775.         for(i=0; i<no_samples; i++)
  776.                 sample[i] = inppw(0xA20);
  777.  
  778. Wow!  That was simple huh?  
  779.  
  780. VI.   Playing a sample
  781. ----------------------
  782.  
  783. You should keep in mind that the EMU8000 does not have a sample length 
  784. register.  So it is always constantly playing.  So how do you keep it from 
  785. playing beyond the end of a sample, if the sample is not looped?
  786.  
  787. You setup a silence loop at the end of the sample.  So for example, you have
  788. a sample that is 26000 samples long, and it is not looped. What you would do
  789. is add 4 or more samples of silence (0) to the end of that sample when
  790. uploading, and set the loopstart, and loopend when playing that sample to
  791. the silence padding at the end of the sample.  Understand?
  792.  
  793. The EMU8000 does not keep track of instruments, and samples.  That is up to
  794. the software.  The EMU8000 only knows playposition, loopstart, and loopend.
  795. and that is for each oscillator.
  796.  
  797. Let's say you wanted to play a sample that was located at offset 0x1000,
  798. which is in the ROM.  And you want to use envelopes and lfo's and you want
  799. it looped.  How would you do that?
  800.  
  801. First you need to allocate an oscillator for playback.  How do you do that?
  802. You can either keep track of the oscillators yourself, or you can go through
  803. all 30/32 (depending if you use ram or not), and check for the one with the
  804. lowest *overall* volume.  The overall volume or overall volume is located in 
  805. register 0x3000+oscillator_no.  0x3000 is a 32bit register, and the overall
  806. volume is located at the high word.  You need to read all 32bits, and then
  807. store only the high word.  After you have found the oscillator, remember its
  808. number (so that when you want to turn off the sample, you know which
  809. oscillator its on).
  810.  
  811. Once you have an oscillator, you can now setup it's parameters.  You do not
  812. need to rewrite any of the parameters for the oscillator unless you know it
  813. has changed or if the parameter is playposition.
  814.  
  815. The first thing you do with that oscillator is disable the volume envelope,
  816. and turn off the volume.  You can disable the volume envelope by writing 0x80 
  817. to the 16-bit register 0x5400. And then you can write 0x0000FFFF to the 32bit
  818. register 0x3000, which sets the overall volume to 0, and the overall filter to
  819. 0xFFFF.  Of course you can set any other filter but, it doesn't matter,
  820. because, the filter envelope hasn't been disabled (EG1).
  821.  
  822. Now, you can set the parameters to your liking without getting clicks, or
  823. twirps, or other strange noises.  You should save play-position for last.
  824. Because, remember, the EMU8000 is always constantly playing.
  825.  
  826. Once you have set all the parameters you can, now enable EG2 (volume eg), by
  827. writing the appropriate value to 0x5400.  (for a full explaination of
  828. 0x5400, refer to section VII.
  829.  
  830. Okay, how do you release or turn off the sample?
  831.  
  832. You write the appropriate values to 0x5400 and 0x7400.  (refer to section VII)
  833.  
  834.  
  835.  
  836. VII.  The registers
  837. -------------------
  838.  
  839. NOTE!!!
  840.  
  841. The scales in this list, may or may not be 100% correct.
  842.  
  843. Format of this list:
  844.  
  845. Register Number         U/O     Base Index      Base Port       W/D
  846. Name
  847.  
  848. Description
  849.  
  850. U/O = Unique/Applies to all oscillators.  If it applies to all oscillators
  851.       you can access the register for any particular oscillator by adding
  852.       the oscillator number to the base index.
  853.  
  854. W/D = The size of the register.  16-bit or 32-bit.  All 16-bits of a 16-bit
  855.       register must be read/write.  And all 32-bits of a 32-bit register
  856.       must be read/write.
  857.  
  858. Unlisted registers are unknown.
  859.  
  860. Registers 0x2400-0x3600 contain effects engine data, and will not be listed.
  861.  
  862. -------------------
  863. 0x0400  O 000 A20 D
  864. FilterQ/DramControl/PlayPosition
  865.  
  866. The upper 4 bits of this register contain the filter resonance coefficient.
  867. Refer to the NRPN LSB 22 in the awe32faq for the coefficient table.
  868.  
  869. The middle 4 bits of this register contain the control nibble of the
  870. oscillator.  0=Normal, 4=Read, 6=Write.  All other values are unknown.
  871.  
  872. The lower 24 bits of this register contain the play position for the
  873. oscillator.  This is the currently playing offset for the oscillator.  It
  874. can be changed on the fly, and is updated continuously, by the EMU8000.
  875.  
  876. Notes!!!
  877.  
  878. Setting the PlayPosition greater than the Loop End Offset, will cause
  879. the oscillator to play in reverse, back to the Loop End Offset.  It's
  880. pretty neat, but appears to be uncontrollable (the rate at which the
  881. samples are played in reverse).
  882.  
  883. -------------------
  884. 0x0800  O 000 E20 W
  885. Initial Pitch
  886.  
  887. The scale for the pitch register is logarithmic.  57344 is Middle C, or
  888. 44100Hz.  Every 4096 is one octave, or double the frequency of the previous
  889. 4096.  Example:  57344-4096 = 22050Hz.  4096/12 is one semitone.  57344+341=
  890. C# or Db (D-Flat).  This register is the initial pitch of the oscillator.
  891.  
  892. -------------------
  893. 0x1000  O 032 620 D
  894. Unknown/ReverbSend/Unknown
  895. 16Bit/8Bit/8bit
  896.  
  897. The purpose of the upper 16bits of this register is unknown.  The upper byte
  898. of the lower word contains the reverb send level.  The range for the 
  899. reverb send level is 0-255 0 is no send, and 255 is full send.  The lower
  900. byte is also unknown.
  901.  
  902. -------------------
  903. 0x1409  U 041 A20 D
  904. Effects Engine Parameter
  905.  
  906. Under the Reverb&Chorus Algorithm this register holds an unknown parameter
  907. for the chorus effect.
  908.  
  909. -------------------
  910. 0x140A  U 042 A20 D
  911. Effects Engine Parameter
  912.  
  913. Under the Reverb&Chorus Algorithm this register holds the modulation
  914. frequency parameter for the chorus effect.
  915.  
  916. -------------------
  917. 0x140D  U 045 A20 D
  918. Effects Engine Parameter
  919.  
  920. Under the Reverb&Chorus Algorithm this register holds an unknown parameter
  921. for the chorus effect.
  922.  
  923. -------------------
  924. 0x140E  U 046 A20 D
  925. Effects Engine Parameter
  926.  
  927. Under the Reverb&Chorus Algorithm this register holds an unknown parameter
  928. for the chorus effect.
  929.  
  930. -------------------
  931. 0x1414  U 052 A20 D
  932. Memory Read Offset
  933.  
  934. This register holds the offset of the data that will be read from the memory
  935. by reading register 0x141A.  This register is automatically incremented each
  936. read.
  937.  
  938. -------------------
  939. 0x1416  U 054 A20 D
  940. Memory Write Offset
  941.  
  942. This register holds the offset of the data that will be write from the memory
  943. by writing register 0x141A.  This register is automatically incremented each
  944. write.
  945.  
  946. -------------------
  947. 0x141A  U 058 A20 W
  948. Memory Read/Write Data
  949.  
  950. This register writes to memory at the offset found in 0x1416, each time this 
  951. register is written to.  This register reads from memory at the offset found
  952. in 0x1414, each time this register is read from.
  953.  
  954. -------------------
  955. 0x161B  U 059 A22 W
  956. 44100Hz Counter
  957.  
  958. This register is incremented every 1/44100th of a second.  When it reaches
  959. 65536, it rolls back to 0.
  960.  
  961. -------------------
  962. 0x1800  O 000 E20 W
  963. Initial Filter/Initial Volume
  964.  
  965. The upper byte of this register contains the initial filter cutoff for that
  966. register.  Zero sets the cutoff at 100Hz, and 255 sets the cutoff at
  967. 8068.75Hz.  The formula for the initial filter cutoff is as follows:
  968.  
  969. InitialFilterCutoff = RegisterValue*31.25Hz+100Hz
  970.  
  971. The lower byte ofthis registers holds the initial volume.  The EMU8000
  972. uses a logarithmic volume scale, with 96dB as the max. volume, and -oo
  973. (infinity), the minimum. A register value of 0 sets the initial volume
  974. of that oscillator to 96dB above silence (-oo dB).  A value of 255 sets
  975. the initial volume to -oo dB.
  976.  
  977. dB to register value:
  978.  
  979. InitialVolume (dB above silence) = 96dB - RegisterValue/16*6dB
  980.  
  981. Linear scale to register vale (if LinearVolume = 0, then register
  982. value = 255):
  983.  
  984. RegisterValue = 20*log(LinearVolume/MaxLinearVolume)*16/6
  985.  
  986. How to understand the decibel system (dB):  12dB is twice as loud as
  987. 6dB.  18dB is twice as loud as 12dB, and four times as loud as 6dB.
  988.  
  989. -------------------
  990. 0x2800  O 064 E20 W
  991. EG1 to Pitch/EG1 to Filter Cutoff
  992.  
  993. The upper byte of this register, contains the ammount the pitch of the
  994. oscillator will be changed by, at the peak of EG1.  This byte is a
  995. signed byte.  The pitch of the oscillator will be doubled at peak, if
  996. this byte is set to 127 (0x7F), if the byte is set to -127 (0x80), then
  997. the pitch will be halved at peak.  Each unit changes the pitch by
  998. 9.375 cents (divide by 100 to get the number of semitones).
  999.  
  1000. The lower byte of this register, contains the ammount the filter cutoff
  1001. of the oscillator will be changed by, at the peak of EG1.  This byte is
  1002. a signed byte.  The  filter cutoff of the oscillator will be multiplied 
  1003. by 8 at peak, if this byte is set to 127 (0x7F), if the byte is set to -127 
  1004. (0x80), then the filter cutoff will be divided by 8 at peak.  Each unit
  1005. changes the filter cutoff by 28.125 cents.
  1006.  
  1007. -------------------
  1008. 0x3000  O 096 620 D
  1009. Overall Volume/Overall Filter Cutoff
  1010.  
  1011. The upper word of this register contains the overall volume of the 
  1012. oscillator.  The overall volume, is the total volume of the oscillator,
  1013. after initial volume, EG2, and possibly LFO1 (i'm not sure).
  1014.  
  1015. The lower word of this reigster contains the overall filter cutoff of
  1016. the oscillator.  The overall volume is the total filter cutoff of the
  1017. oscillator after initial filter cutoff, EG1, and possibly LFO1 (i'm not
  1018. sure).
  1019.  
  1020. -------------------
  1021. 0x3800  O 096 E20 W
  1022. LFO1 to Pitch/LFO1 to Filter Cutoff
  1023.  
  1024. This register is exactly the same as register 0x2800, except it controls
  1025. the LFO1 instead of EG1.
  1026.  
  1027. -------------------
  1028. 0x4400  O 128 A20 W
  1029. EG2 Delay Time
  1030.  
  1031. This register controls the time EG2 will wait before beginning the
  1032. attack.
  1033.  
  1034. RegisterValue = 32768-(DelayTime_ms*1000/725)
  1035.  
  1036. The range for DelayTime is [0ms -> 23756.8ms]
  1037.  
  1038. -------------------
  1039. 0x4600  O 128 A22 W
  1040. EG2 Hold Time/EG2 Attack Time
  1041.  
  1042. The upper byte of the register contains the time at which EG2 will
  1043. stay at peak before beginning the decay.
  1044.  
  1045. RegisterValue = 127-(HoldTime_ms/92)
  1046.  
  1047. The range for HoldTime is [0ms -> 11684ms]
  1048.  
  1049. The lower byte of the register contains the attack, the time during
  1050. which EG2 fades from 0 to peak.
  1051.  
  1052.         if AttackTime_ms >= 360ms:
  1053.  
  1054.         RegisterValue = 11878/AttackTime_ms - 1
  1055.  
  1056.         if AttackTime_ms < 360ms and AttackTime != 0:
  1057.  
  1058.         RegisterValue = 32 + [16/log(1/2)] * log(360_ms/AttackTime_ms)
  1059.  
  1060.         if AttackTime_ms == 0
  1061.  
  1062.         RegisterValue = 0x7F
  1063.  
  1064. The range for attack time is [0ms -> 11878ms]
  1065.  
  1066. -------------------
  1067. 0x4800  O 128 E20 W
  1068. LFO1 to Volume/LFO1 Frequency
  1069.  
  1070. The upper byte contains the the ammount the volume of the oscillator
  1071. will be changed by at the peak of LFO1.  This byte is signed.
  1072.  
  1073. RegisterValue = Volume_dB * 12/128
  1074.  
  1075. The range for Volume_dB is [-12dB -> 12dB]
  1076.  
  1077. The lower byte contains the frequency at which LFO1 oscillates.
  1078.  
  1079. RegisterValue = Frequency_Hz * 21.44/256
  1080.  
  1081. -------------------
  1082. 0x5400  O 160 A20 W
  1083. EG2 Override/EG2 Sustain/EG2 Decay, Release or EG2 Ramper
  1084.  
  1085. If the MSB (most significant bit or bit 15) of this register is set,
  1086. the Decay/Release will begin immediately, overriding the Delay, Attack,
  1087. and Hold.  Otherwise the Decay/Release will wait until the Delay, Attack,
  1088. and Hold are finished.  If you set the MSB of this register, you can use
  1089. it as a volume ramper, as on the GUS.  The upper byte (except the MSB),
  1090. contains the destination volume, and the lower byte contains the ramp time.
  1091.  
  1092. Sustain Portion:
  1093.  
  1094. RegisterValue = SustainLevel_dB*4/3
  1095.  
  1096. Decay/Release Portion:
  1097.  
  1098. RegisterValue = 2*log(1/2)*log(23756_ms/DecayTime_ms)
  1099.  
  1100. range: [0ms, 23756ms], obviously at 0ms, the register value is 127.
  1101.  
  1102. Notes!!!
  1103.  
  1104. Setting the sustain of this register above zero, turns on the volume.
  1105. Basically, setting this register with proper decay, and sustain time
  1106. (any value other than zero), will start the _audible_ playing of the
  1107. sample.  (remember: the emu is always constantly playing).
  1108.  
  1109. Setting the sustain to zero, and the decay to appropriate time, will
  1110. start the release of the sample.  Thus turning off the sample,
  1111. _audibly_.
  1112.  
  1113. What I did in my modplayer (AWEMod), is each time I turned the note on,
  1114. I set the upper byte to 0xFF, which sets the upper byte, and sets the
  1115. sustain level to 96dB, and set the decay time to 0x7F (0 ms).  This
  1116. gave me the sharpest attacks, because EG2, skips the delay, attack,
  1117. hold, and goes straight to sustain.
  1118.  
  1119. -------------------
  1120. 0x5600  O 160 A22 W
  1121. LFO1 Delay Time
  1122.  
  1123. This is exactly the same as EG1 Delay Time, register 0x4400.
  1124.  
  1125. -------------------
  1126. 0x5800  O 160 E20 W
  1127. LFO2 to Pitch/LFO2 Frequency
  1128.  
  1129. The format of the upper byte (LFO2 to Pitch) is exactly the same as for
  1130. EG1 (register 0x2800), and the format of the lower byte is exactly the
  1131. same as for register 0x4800 (LFO1 Frequency).
  1132.  
  1133. -------------------
  1134. 0x6000  O 192 620 D
  1135. Pan Level/Loop Start Offset
  1136.  
  1137. The highest byte contains the pan level.  Zero is full right, 128 is
  1138. dead center, and 255 is full left.  Simple.
  1139.  
  1140. The last 3 bytes are the Loop Start Offset.
  1141.  
  1142. -------------------
  1143. 0x6400  O 192 A20 W
  1144. EG1 Delay Time
  1145.  
  1146. Same as EG2 Delay Time, register 0x4400.
  1147.  
  1148. -------------------
  1149. 0x6600  O 192 A22 W
  1150. EG1 Hold Time/EG1 Attack Time
  1151.  
  1152. Same as EG2 Hold/EG2 Attack, register 0x4600.
  1153.  
  1154. -------------------
  1155. 0x7000  O 224 620 D
  1156. Chorus Send/Loop End Offset
  1157.  
  1158. The highest byte contains the Chorus Send level.  Zero is none, and
  1159. 255 is full.  The last 3 bytes contain the Loop End Offset.
  1160.  
  1161. Notes!!!
  1162.  
  1163. Setting the Loop Start Offset and the Loop End Offset to the same
  1164. value, will cause the oscillator to loop the entire memory.
  1165.  
  1166. -------------------
  1167. 0x7400  O 224 A20 W
  1168. EG1 Override/EG1 Sustain/EG1 Decay, Release or EG1 Ramper
  1169.  
  1170. This is exactly the same as register 0x5400.  Except it controls the
  1171. filter cutoff, and pitch of the oscillator.
  1172.  
  1173. -------------------
  1174. 0x7600  O 224 A22 W
  1175. LFO2 Delay
  1176.  
  1177. Same as LFO1 Delay, register 0x5600.
  1178.  
  1179.  
  1180. VIII. Effects Engine Data
  1181. -------------------------
  1182.  
  1183. Data to reset/clear the engine, not quite sure what it does (128 Words):
  1184.  
  1185. 0x3FF,0x30,0x7FF,0x130,0xBFF,0x230,0xFFF,0x330,0x13FF,0x430,0x17FF,0x530,
  1186. 0x1BFF,0x630,0x1FFF,0x730,0x23FF,0x830,0x27FF,0x930,0x2BFF,0xA30,0x2FFF,0xB30,
  1187. 0x33FF,0xC30,0x37FF,0xD30,0x3BFF,0xE30,0x3FFF,0xF30,0x43FF,0x030,0x47FF,0x130,
  1188. 0x4BFF,0x230,0x4FFF,0x330,0x53FF,0x430,0x57FF,0x530,0x5BFF,0x630,0x5FFF,0x730,
  1189. 0x63FF,0x830,0x67FF,0x930,0x6BFF,0xA30,0x6FFF,0xB30,0x73FF,0xC30,0x77FF,0xD30,
  1190. 0x7BFF,0xE30,0x7FFF,0xF30,0x83FF,0x030,0x87FF,0x130,0x8BFF,0x230,0x8FFF,0x330,
  1191. 0x93FF,0x430,0x97FF,0x530,0x9BFF,0x630,0x9FFF,0x730,0xA3FF,0x830,0xA7FF,0x930,
  1192. 0xABFF,0xA30,0xAFFF,0xB30,0xB3FF,0xC30,0xB7FF,0xD30,0xBBFF,0xE30,0xBFFF,0xF30,
  1193. 0xC3FF,0x030,0xC7FF,0x130,0xCBFF,0x230,0xCFFF,0x330,0xD3FF,0x430,0xD7FF,0x530,
  1194. 0xDBFF,0x630,0xDFFF,0x730,0xE3FF,0x830,0xE7FF,0x930,0xEBFF,0xA30,0xEFFF,0xB30,
  1195. 0xF3FF,0xC30,0xF7FF,0xD30,0xFBFF,0xE30,0xFFFF,0xF30
  1196.  
  1197. Reverb&Chorus Algorithm Data [Hall 2, Chorus 3] (128 Words):
  1198.  
  1199. 0x0C10,0x8470,0x14FE,0xB488,0x167F,0xA470,0x18E7,0x84B5,0x1B6E,0x842A,0x1F1D,
  1200. 0x852A,0x0DA3,0x0F7C,0x167E,0x7254,0x0000,0x842A,0x0001,0x852A,0x18E6,0x0BAA,
  1201. 0x1B6D,0x7234,0x229F,0x8429,0x2746,0x8529,0x1F1C,0x6E7,0x229E,0x7224,0x0DA4,
  1202. 0x8429,0x2C29,0x8529,0x2745,0x7F6,0x2C28,0x7254,0x383B,0x8428,0x320F,0x8528,
  1203. 0x320E,0xF02,0x1341,0x7264,0x3EB6,0x8428,0x3EB9,0x8528,0x383A,0xFA9,0x3EB5,
  1204. 0x7294,0x3EB7,0x8474,0x3EBA,0x8575,0x3EB8,0x44C3,0x3EBB,0x45C3,0x0000,0xA404,
  1205. 0x0001,0xA504,0x141F,0x671,0x14FD,0x287,0x3EBC,0xE610,0x3EC8,0xC7B,0x031A,
  1206. 0x07E6,0x3EC8,0x86F7,0x3EC0,0x821E,0x3EBE,0xD280,0x3EBD,0x21F,0x3ECA,0x0386,
  1207. 0x3EC1,0xC03,0x3EC9,0x31E,0x3ECA,0x8C4C,0x3EBF,0xC55,0x3EC9,0xC280,0x3EC4,
  1208. 0xBC84,0x3EC8,0xEAD,0x3EC8,0xD380,0x3EC2,0x8F7E,0x3ECB,0x219,0x3ECB,0xD2E6,
  1209. 0x3EC5,0x31F,0x3EC6,0xC380,0x3EC3,0x327F,0x3EC9,0x265,0x3EC9,0x8319,0x1342,
  1210. 0xD3E6,0x3EC7,0x337F,0x0000,0x8365,0x1420,0x9570
  1211.  
  1212. Modifications to effects engine data registers to get other reverb&chorus
  1213. variations (also stuff about custom effects), and different EQ's:
  1214.  
  1215. Registers to write the Chorus Parameters to (all are 16-bit, unless noted):
  1216.  
  1217. 0x3409
  1218. 0x340C
  1219. 0x3603
  1220. 0x1409 (32-Bit)
  1221. 0x140A (32-Bit)
  1222. then write 0x8000 to 0x140D (32-Bit)
  1223. and then 0x0000 to 0x140E (32-Bit)
  1224.  
  1225. Chorus Parameters:
  1226.  
  1227. Chorus 1  Chorus 2  Chorus 3  Chorus 4  Feedback  Flanger
  1228.  
  1229. 0xE600    0xE608    0xE610    0xE620    0xE680    0xE6E0
  1230. 0x03F6    0x031A    0x031A    0x0269    0x04D3    0x044E
  1231. 0xBC2C    0xBC6E    0xBC84    0xBC6E    0xBCA6    0xBC37
  1232. 0x0000    0x0000    0x0000    0x0000    0x0000    0x0000
  1233. 0x006D    0x017C    0x0083    0x017C    0x005B    0x0026
  1234.  
  1235. Short Delay         Short Delay + Feedback
  1236.  
  1237. 0xE600              0xE6C0
  1238. 0x0B06              0x0B06
  1239. 0xBC00              0xBC00
  1240. 0xE000              0xE000
  1241. 0x0083              0x0083
  1242.  
  1243. Registers to write the Reverb Parameters to (they are all 16-bit):
  1244.  
  1245. 0x2403,0x2405,0x361F,0x2407,0x2614,0x2616,0x240F,0x2417,
  1246. 0x241F,0x2607,0x260F,0x2617,0x261D,0x261F,0x3401,0x3403,
  1247. 0x2409,0x240B,0x2411,0x2413,0x2419,0x241B,0x2601,0x2603,
  1248. 0x2609,0x260B,0x2611,0x2613
  1249.  
  1250. Reverb Parameters:
  1251.  
  1252. Room 1:
  1253.  
  1254. 0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,0x72A4,
  1255. 0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,0xA490,0xA590,
  1256. 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  1257. 0x8428,0x8528,0x8428,0x8528
  1258.  
  1259. Room 2:
  1260.  
  1261. 0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
  1262. 0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540,
  1263. 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  1264. 0x8428,0x8528,0x8428,0x8528
  1265.  
  1266. Room 3:
  1267.  
  1268. 0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
  1269. 0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,0xA490,0xA590,
  1270. 0x842C,0x852C,0x842C,0x852C,0x842B,0x852B,0x842B,0x852B,
  1271. 0x842A,0x852A,0x842A,0x852A
  1272.  
  1273. Hall 1:
  1274.  
  1275. 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
  1276. 0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540,
  1277. 0x842B,0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A,
  1278. 0x8429,0x8529,0x8429,0x8529
  1279.                            
  1280. Hall 2:
  1281.                                      
  1282. 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,0x7234,
  1283. 0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,0xA404,0xA504,
  1284. 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  1285. 0x8428,0x8528,0x8428,0x8528 
  1286.  
  1287. Plate:
  1288.      
  1289. 0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,0x7234,
  1290. 0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,0xA440,0xA540,
  1291. 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  1292. 0x8428,0x8528,0x8428,0x8528
  1293.  
  1294. Delay:
  1295.  
  1296. 0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,0x7204,
  1297. 0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF,
  1298. 0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
  1299. 0x8420,0x8520,0x8420,0x8520
  1300.  
  1301. Panning Delay:
  1302.  
  1303. 0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,0x7204,
  1304. 0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF,
  1305. 0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
  1306. 0x8420,0x8520,0x8420,0x8520
  1307.  
  1308. Registers to write the EQ Parameters to (16-Bit):
  1309.  
  1310. Bass:
  1311.  
  1312. 0x3601
  1313. 0x3611
  1314.  
  1315. Treble:
  1316.  
  1317. 0x3411
  1318. 0x3413
  1319. 0x341B
  1320. 0x3607
  1321. 0x360B
  1322. 0x360D
  1323. 0x3617
  1324. 0x3619
  1325.  
  1326. Total:
  1327.  
  1328. write the 0x0263 + 3rd parameter of the Bass EQ + 9th parameter of Treble EQ to 0x3615.
  1329. write the 0x8363 + 3rd parameter of the Bass EQ + 9th parameter of Treble EQ to 0x3615.
  1330.  
  1331.  
  1332. Bass Parameters:
  1333.  
  1334. 0:      1:      2:      3:      4:      5:      6:      7:      8:      9:      10:     11:
  1335.  
  1336. 0xD26A  0xD25B  0xD24C  0xD23D  0xD21F  0xC208  0xC219  0xC22A  0xC24C  0xC26E  0xC248  0xC26A
  1337. 0xD36A  0xD35B  0xD34C  0xD33D  0xC31F  0xC308  0xC308  0xC32A  0xC34C  0xC36E  0xC384  0xC36A
  1338. 0x0000  0x0000  0x0000  0x0000  0x0000  0x0001  0x0001  0x0001  0x0001  0x0001  0x0002  0x0002
  1339.  
  1340. Treble Parameters:
  1341.  
  1342. 0:      1:      2:      3:      4:      5:      6:      7:      8:      9:      10:     11:
  1343. 0x821E  0x821E  0x821E  0x821E  0x821E  0x821E  0x821E  0x821E  0x821E  0x821E  0x821D  0x821C
  1344. 0xC26A  0xC25B  0xC24C  0xC23D  0xC21F  0xD208  0xD208  0xD208  0xD208  0xD208  0xD219  0xD22A
  1345. 0x031E  0x031E  0x031E  0x031E  0x031E  0x031E  0x031E  0x031E  0x031E  0x031E  0x031D  0x031C
  1346. 0xC36A  0xC35B  0xC34C  0xC33D  0xC31F  0xD308  0xD308  0xD308  0xD308  0xD308  0xD319  0xD32A
  1347. 0x021E  0x021E  0x021E  0x021E  0x021E  0x021E  0x021D  0x021C  0x021A  0x0219  0x0219  0x0219
  1348. 0xD208  0xD208  0xD208  0xD208  0xD208  0xD208  0xD219  0xD22A  0xD24C  0xD26E  0xD26E  0xD26E
  1349. 0x831E  0x831E  0x831E  0x831E  0x831E  0x831E  0x831D  0x831C  0x831A  0x8319  0x8319  0x8319
  1350. 0xD308  0xD308  0xD308  0xD308  0xD308  0xD308  0xD3019 0xD32A  0xD34C  0xD36E  0xD36E  0xD36E
  1351. 0x0001  0x0001  0x0001  0x0001  0x0001  0x0002  0x0002  0x0002  0x0002  0x0002  0x0002  0x0002
  1352.  
  1353.  
  1354. To see what the parameters do, use the program FXTweak, which I wrote and included with the
  1355. programming guide.
  1356.  
  1357. IX.   Other documents you should refer to
  1358. -----------------------------------------
  1359.  
  1360. ftp.cdrom.com:/pub/demos/music/programs/players/omega06.zip
  1361.  
  1362. This is the only modplayer for the AWE32 that comes with source code.
  1363. Although the source, isn't very helpful, but it's working code.
  1364.  
  1365. ftp.creaf.com:/pub/creative/files/awe/awe32faq.exe
  1366.  
  1367. Great resource.  Refer to NRPN 22, in this faq, for a description of
  1368. the resonance coefficients.
  1369.